package com.xbongbong.paas.service.stage.execute;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.PaasStageEntity;
import com.xbongbong.paas.domain.entity.StageProcessEntity;
import com.xbongbong.paas.domain.entity.StageWorkLogEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.dto.InsertDTO;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.StageTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.WorkflowTransferHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.CrmLogMemoConstant;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasProcessDataModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.pojo.dto.StartProcessDTO;
import com.xbongbong.paas.pojo.vo.StartProcessVO;
import com.xbongbong.paas.service.PaasFormExplainService;
import com.xbongbong.paas.service.PaasFormService;
import com.xbongbong.paas.service.ProModelService;
import com.xbongbong.paas.service.dynamic.crm.strategy.DynamicStrategyFactory;
import com.xbongbong.paas.service.dynamic.crm.strategy.MainBusinessDynamicStrategy;
import com.xbongbong.paas.service.stage.StageJumpHandle;
import com.xbongbong.paas.service.workflow.trigger.WorkflowFormDataOperationService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.pro.businessrule.pojo.BusinessRuleInfoPojo;
import com.xbongbong.pro.businesstage.pojo.dto.CommonJumpDTO;
import com.xbongbong.pro.businesstage.pojo.dto.StageFinishWorkDTO;
import com.xbongbong.pro.businesstage.pojo.dto.StageGetDTO;
import com.xbongbong.pro.businesstage.pojo.dto.StageJumpDealDTO;
import com.xbongbong.pro.businesstage.pojo.dto.StageJumpSpecialDealDTO;
import com.xbongbong.pro.businesstage.pojo.dto.StageJumpValidateDTO;
import com.xbongbong.pro.businesstage.pojo.vo.StageFinishWorkVO;
import com.xbongbong.pro.businesstage.pojo.vo.StageGetVO;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.constant.SymbolConstant;
import com.xbongbong.pro.customercommunicate.pojo.dto.CustomerDynamicAddDTO;
import com.xbongbong.pro.dictionary.pojo.DictionaryPojo;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.dynamic.pojo.dto.DynamicStageJumpDTO;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.PaasStageEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BomErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.CustomerStageErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.PublicPoolErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.workflow.TriggerEventTypeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.formexplain.pojo.dto.LinkFormItemDTO;
import com.xbongbong.pro.log.pojo.DetailLogPojo;
import com.xbongbong.pro.message.constant.CustomerPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.help.PushHelper;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.rabbitmq.producer.BaseProducer;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.weblist.pojo.dto.SaasBaseDTO;
import com.xbongbong.pro.workflow.enums.WorkflowExecutionTypeEnum;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.process.operate.ProcessStartHelp;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.dao.CustomerDao;
import com.xbongbong.saas.domain.entity.CustomerStageEntity;
import com.xbongbong.saas.domain.entity.CustomerStageLogEntity;
import com.xbongbong.saas.domain.entity.CustomerUserEntity;
import com.xbongbong.saas.domain.entity.CustomerWorkLogEntity;
import com.xbongbong.saas.domain.entity.DataDictionaryEntity;
import com.xbongbong.saas.domain.entity.UserTeamEntity;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.ProjectLogEnum;
import com.xbongbong.saas.enums.RuleSettingEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContactEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.dictionary.DictionaryEnum;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.CustomerStageLogModel;
import com.xbongbong.saas.model.CustomerStageModel;
import com.xbongbong.saas.model.CustomerUserModel;
import com.xbongbong.saas.model.CustomerWorkLogModel;
import com.xbongbong.saas.model.DataDictionaryModel;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.service.CustomerCommunicateService;
import com.xbongbong.saas.service.DictionaryService;
import com.xbongbong.saas.service.ScoreCalculateService;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.workflow.domain.entity.WorkflowBackupDataEntity;
import com.xbongbong.workflow.domain.entity.WorkflowEntity;
import com.xbongbong.workflow.domain.entity.WorkflowExecutionEntity;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTransferDataEntity;
import com.xbongbong.workflow.model.WorkflowBackupDataModel;
import com.xbongbong.workflow.model.WorkflowNodeModel;
import com.xbongbong.workflow.model.WorkflowTaskModel;
import com.xbongbong.workflow.model.WorkflowTransferDataModel;
import com.xbongbong.workflow.pojo.Data;
import com.xbongbong.workflow.pojo.WorkflowRabbitmqDTO;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.pojo.nodes.FormTriggerNode;
import com.xbongbong.workflow.producer.WorkflowProducer;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;

/**
 * @author 吴峰
 * @date 2021/11/22 19:25
 */
@Slf4j
@Service("customerStageExecuteHandleImpl")
public class CustomerStageExecuteHandleImpl extends AbstractStageExecuteHandle {

    @Resource
    private CustomerModel customerModel;
    @Resource
    private CustomerStageLogModel customerStageLogModel;
    @Resource
    private CustomerStageModel customerStageModel;
    @Resource
    private CustomerWorkLogModel customerWorkLogModel;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasFormService paasFormService;
    @Resource
    private ScoreCalculateService scoreCalculateService;
    @Resource
    private ProModelService proModelService;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private PushHelper pushHelper;
    @Resource
    @Lazy
    private CustomerCommunicateService customerCommunicateService;
    @Resource
    private BaseProducer baseProducer;
    @Resource
    private DictionaryService dictionaryService;
    @Resource
    private DataDictionaryModel dataDictionaryModel;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private WorkflowFormDataOperationService workflowFormDataOperationService;
    @Resource
    private WorkflowNodeModel workflowNodeModel;
    @Resource
    private CustomerUserModel customerUserModel;
    @Resource
    private WorkflowBackupDataModel workflowBackupDataModel;
    @Resource
    private WorkflowProducer workflowProducer;
    @Resource
    private ProcessStartHelp processStartHelp;
    @Resource
    private EsHelper esHelper;
    @Resource
    private PaasFormExplainService paasFormExplainService;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private PaasProcessDataModel paasProcessDataModel;
    @Resource
    private WorkflowTransferDataModel workflowTransferDataModel;
    @Resource
    private Map<Integer, StageJumpHandle> stageJumpMap;
    @Resource
    private WorkflowTaskModel workflowTaskModel;
    @Resource
    private DynamicStrategyFactory dynamicStrategyFactory;
    @Resource
    private CustomerDao customerDao;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private IndexTypeModel indexTypeModel;

    @Override
    public Integer type() {
        return XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode();
    }

    @Override
    public void validate(StageJumpValidateDTO stageJumpValidateDTO) throws XbbException {
        String corpid = stageJumpValidateDTO.getCorpid();
        Long dataId = stageJumpValidateDTO.getDataId();
        PaasStageEntity toStageEntity = stageJumpValidateDTO.getToStageEntity();
        CustomerEntityExt customerEntityExt = customerModel.getByKey(dataId, corpid);
        //公海客户不允许更改客户阶段
        Integer isPublic = customerEntityExt.getData().getInteger(CustomerManagementEnum.IS_PUBLIC.getAttr());
        if (Objects.equals(isPublic, 1)) {
            throw new XbbException(PublicPoolErrorCodeEnum.API_ERROR_218001);
        }
        PaasFormExplainEntity explain = paasFormExplainModel.getByFormId(customerEntityExt.getFormId(), customerEntityExt.getCorpid());
        if (Objects.isNull(explain)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explain.getExplains(), null);
        //校验客户转跳到流失阶段的必填校验
        if (Objects.nonNull(toStageEntity)) {
            boolean isLose = Objects.equals(StageTypeEnum.FAIL_STAGE.getType(), toStageEntity.getType());
            if (isLose) {
                FieldAttrEntity fieldAttrEntity = explainMap.getOrDefault(CustomerManagementEnum.WASTAGE.getAttr(), new FieldAttrEntity());
                boolean wastage = Objects.equals(fieldAttrEntity.getRequired(), 1) && Objects.equals(fieldAttrEntity.getIsOpen(), 1) && Objects.equals(fieldAttrEntity.getVisible(), 1);
                if (wastage && (Objects.isNull(stageJumpValidateDTO.getReasonId()) || stageJumpValidateDTO.getReasonId() <= 0)) {
                    //无效原因必填
                    throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238002);
                }
                FieldAttrEntity memoField = explainMap.getOrDefault(CustomerManagementEnum.WASTAGE_MEMO.getAttr(), new FieldAttrEntity());
                boolean memoRequired = Objects.equals(memoField.getRequired(), 1) && Objects.equals(memoField.getIsOpen(), 1) && Objects.equals(memoField.getVisible(), 1);
                if (memoRequired && StringUtil.isEmpty(stageJumpValidateDTO.getMemo())) {
                    throw new XbbException(BomErrorCodeEnum.API_ERROR_242019);
                }
            }
        }
    }

    @Override
    public StageGetVO get(StageGetDTO stageGetDTO) throws XbbException {
        StageGetVO stageGetVO = new StageGetVO();
        stageGetVO.setStageShowType(0);
        String corpid = stageGetDTO.getCorpid();
        Long formId = stageGetDTO.getFormId();
        Long dataId = stageGetDTO.getDataId();
        Integer saasMark = stageGetDTO.getSaasMark();
        CustomerEntityExt customerEntityExt = new CustomerEntityExt();
        //老审批流转状态
        Integer approveFlowStatus = null;
        //工作流审批流转状态
        Integer workflowFlowStatus = null;

        if (Objects.equals(stageGetDTO.getApproveType(), BasicConstant.ONE)) {
            PaasProcessDataEntity processDataEntity = paasProcessDataModel.getByTaskId(stageGetDTO.getProcessTaskId(), corpid);
            customerEntityExt.setData(JSONObject.parseObject(processDataEntity.getData()));
            approveFlowStatus = processDataEntity.getFlowStatus();
        } else if (Objects.equals(stageGetDTO.getApproveType(), BasicConstant.TWO)) {
            WorkflowTransferDataEntity workflowTransferDataEntity = workflowTransferDataModel.getByTaskId(stageGetDTO.getProcessTaskId(), corpid);
            JSONObject workFlowData = workflowTransferDataEntity.getData();
            JSONObject dataJSONObject = workFlowData.getJSONObject("data");
            customerEntityExt.setData(dataJSONObject.getJSONObject("data"));
            WorkflowTaskEntity workflowTaskEntity = workflowTaskModel.getByKey(stageGetDTO.getProcessTaskId(), corpid);
            workflowFlowStatus = Objects.isNull(workflowTaskEntity) ? null : workflowTaskEntity.getFlowStatus();
        } else {
            customerEntityExt = customerModel.getByKey(dataId, corpid);
            // 移动端透传关联数据时入参取不到最新formid
            formId = customerEntityExt.getFormId();
        }
        PaasFormExplainEntity explain = paasFormExplainModel.getByFormId(formId, corpid);
        if (Objects.isNull(explain)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explain.getExplains(), null);

        boolean checkshow = checkshow(stageGetDTO, customerEntityExt);
        if (!checkshow) {
            stageGetVO.setStageShowType(0);
            return stageGetVO;
        }
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Long stageProcessId = customerEntityExt.getData().getLong(CustomerManagementEnum.STAGE_PROCESS_ID.getAttr());
        String customerStage = customerEntityExt.getData().getString(CustomerManagementEnum.CUSTOMER_STAGE.getAttr());
        StageProcessEntity stageProcessEntity = getStageProcessEntity(stageGetDTO, stageProcessId, customerStage, explainMap, customerEntityExt);
        if (Objects.isNull(stageProcessEntity)) {
            return stageGetVO;
        }
        stageProcessId = stageProcessEntity.getId();
        List<CustomerStageLogEntity> customerStageLogEntities = new ArrayList<>();
        if (Objects.nonNull(dataId) && !Objects.equals(dataId, BasicConstant.ZERO_LONG)) {
            params.put("corpid", corpid);
            params.put("formId", formId);
            params.put("dataId", dataId);
            params.put("del", 0);
            customerStageLogEntities = customerStageLogModel.findEntitys(params);
            if (Objects.equals(corpid, "dinge3fa697f86d461d2") && CollectionsUtil.isNotEmpty(customerStageLogEntities) && !Objects.equals(stageGetDTO.getApproveType(), BasicConstant.ONE) && !Objects.equals(stageGetDTO.getApproveType(), BasicConstant.TWO)) {
                List<CustomerStageLogEntity> currentStageLogList = customerStageLogEntities.stream().filter(stageLog -> Objects.equals(stageLog.getIsNow(), 1)).collect(Collectors.toList());
                if (CollectionsUtil.isNotEmpty(currentStageLogList) && Objects.equals(currentStageLogList.size(), 1)) {
                    CustomerStageLogEntity currentStageLog = currentStageLogList.get(0);
                    String formDataCode = customerEntityExt.getData().getString(CustomerManagementEnum.CUSTOMER_STAGE.getAttr());
                    if (!Objects.equals(formDataCode, currentStageLog.getStageCode())) {
                        customerEntityExt.getData().put(CustomerManagementEnum.CUSTOMER_STAGE.getAttr(), currentStageLog.getStageCode());
                        customerDao.update(customerEntityExt);
                        InsertDTO insertDTO = new InsertDTO();
                        insertDTO.setEsId(corpid + "_" + customerEntityExt.getId());
                        Map<String, Object> map = new HashMap<>();
                        JSONObject object = new JSONObject();
                        object.put(CustomerManagementEnum.CUSTOMER_STAGE.getAttr(), currentStageLog.getStageCode());
                        map.put(StringConstant.JSON_DATA, object);
                        insertDTO.setSource(map);
                        IndexTypeEnum indexTypeEnum = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
                        insertDTO.setIndexTypeEnum(indexTypeEnum);
                        paasEsModel.update(insertDTO);
                    }
                }
            }
        }
        params.clear();
        params.put("corpid", corpid);
        params.put("formId", formId);
        params.put("stageProcessId", stageProcessId);
        params.put("del", 0);
        params.put("orderByStr", "sort desc,add_time asc");
        List<CustomerStageEntity> clueStageEntities = customerStageModel.findEntitys(params);
        Integer stageRation = customerEntityExt.getData().getInteger(CustomerManagementEnum.STAGE_RATIO.getAttr());
        // 主逻辑
        stageGetVO = stageGet(stageRation, customerEntityExt, stageProcessEntity, stageGetDTO, customerStageLogEntities, clueStageEntities,approveFlowStatus, workflowFlowStatus);
        stageGetVO.setStageProcessId(stageProcessId);

        List<FieldAttrEntity> explainList = new ArrayList<>();
        explainList.add(explainMap.get(CustomerManagementEnum.WASTAGE.getAttr()));
        explainList.add(explainMap.get(CustomerManagementEnum.WASTAGE_MEMO.getAttr()));
        stageGetVO.setExplainList(explainList);
        return stageGetVO;
    }

    @Override
    public StageFinishWorkVO finishWork(StageFinishWorkDTO stageFinishWorkDTO) throws XbbException {
        String corpid = stageFinishWorkDTO.getCorpid();
        Long formId = stageFinishWorkDTO.getFormId();
        Long dataId = stageFinishWorkDTO.getDataId();
        StageFinishWorkVO stageFinishWorkVO = stageFinishWork(stageFinishWorkDTO);
        long time = DateTimeUtil.getInt();
        if (stageFinishWorkDTO.getIsFinished() == 1) {
            //每完成一项阶段工作时的完成时间影响客户的最后跟进时间
            Boolean flag = paasFormService.getSingleRuleList(corpid, RuleSettingEnum.COMPLETE_PHASE_WORK_COMPLETION_TIME.getConfig(), formId);
            if (flag) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put(CustomerManagementEnum.LAST_CONNECT_TIME.getAttr(), time);
                UpdateDataEntity updateData = ExplainUtil.getUpdateData(dataId, jsonObject, corpid);
                log.info("====================================阶段完成后更新客户时间1:" + DateTimeUtil.getLong());
                customerModel.updateBatch(Collections.singletonList(updateData), corpid, WriteRequest.RefreshPolicy.NONE);
                log.info("====================================阶段完成后更新客户时间2:" + DateTimeUtil.getLong());
                //评分更新 （客户阶段工作， 点击“完成工作”，如果表单设置了更新规则，那么会修改最后跟进时间）
                scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT, corpid, updateData.getId(), null);
                log.info("====================================阶段完成后更新客户时间3:" + DateTimeUtil.getLong());
            }
        }
        return stageFinishWorkVO;
    }

    @Override
    public void stageWorkLogSave(StageWorkLogEntity stageWorkLogEntity) throws XbbException {
        CustomerWorkLogEntity customerWorkLogEntity = new CustomerWorkLogEntity();
        BeanUtils.copyProperties(stageWorkLogEntity, customerWorkLogEntity);
        customerWorkLogModel.save(customerWorkLogEntity);
    }

    @Override
    public List<StageWorkLogEntity> stageWorkLogFindEntitys(Map<String, Object> params) {
        List<CustomerWorkLogEntity> entitys = customerWorkLogModel.findEntitys(params);
        return Arrays.asList(entitys.toArray(new StageWorkLogEntity[0]));
    }

    @Override
    public boolean checkshow(StageGetDTO stageGetDTO, PaasFormDataEntityExt paasFormDataEntityExt) throws XbbException {
        String corpid = stageGetDTO.getCorpid();
        Long dataId = stageGetDTO.getDataId();
        if (Objects.equals(stageGetDTO.getApproveType(), BasicConstant.ONE) || Objects.equals(stageGetDTO.getApproveType(), BasicConstant.TWO)) {
            return true;
        }
        if (Objects.isNull(paasFormDataEntityExt)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        Long formId = paasFormDataEntityExt.getFormId();
        PaasFormExplainEntity explain = paasFormExplainModel.getByFormId(formId, corpid);
        if (Objects.isNull(explain)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explain.getExplains(), null);
        FieldAttrEntity stageEntity = explainMap.get(CustomerManagementEnum.CUSTOMER_STAGE.getAttr());
        //协同团队
        Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        JSONObject data = paasFormDataEntityExt.getData();
        Boolean isPublic = data.getInteger(CustomerManagementEnum.IS_PUBLIC.getAttr()).equals(1);
        userTeamService.getUserIdMap(Collections.singletonList(paasFormDataEntityExt.getId()), corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), isPublic, mainUserMap, coUserMap);
        // 当前数据的创建人、负责人、协同人、当前操作人
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        BeanUtil.copyProperties(stageGetDTO, handlerExplainDTO);
        handlerExplainDTO.setOwnerId(mainUserMap.getOrDefault(paasFormDataEntityExt.getId(), new ArrayList<>()));
        handlerExplainDTO.setCoUserId(coUserMap.getOrDefault(paasFormDataEntityExt.getId(), new ArrayList<>()));
        handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
        if (!CommonHelp.ifStageOpen(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), explainMap, handlerExplainDTO)) {
            return false;
        }
        if (Objects.nonNull(stageEntity)) {
            Integer stageProcessIdIsOpen = stageEntity.getIsOpen();
            Boolean fieldNeedHide = ExplainUtil.isFieldNeedHide(stageEntity, handlerExplainDTO);
            if (stageProcessIdIsOpen != 1 || fieldNeedHide) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean checkFieldEditable(SaasBaseDTO saasBaseDTO) throws XbbException {
        String corpid = saasBaseDTO.getCorpid();
        Integer businessType = saasBaseDTO.getBusinessType();
        Integer saasMark = saasBaseDTO.getSaasMark();
        Long dataId = saasBaseDTO.getDataId();
        PaasFormDataEntityExt paasFormDataEntityExt = (PaasFormDataEntityExt) proModelService.getFormDataEntity(corpid, saasMark, businessType, dataId);
        if (Objects.isNull(paasFormDataEntityExt)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        Long formId = paasFormDataEntityExt.getFormId();
        PaasFormExplainEntity explain = paasFormExplainModel.getByFormId(formId, corpid);
        if (Objects.isNull(explain)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explain.getExplains(), null);
        //协同团队
        Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        JSONObject data = paasFormDataEntityExt.getData();
        Boolean isPublic = data.getInteger(CustomerManagementEnum.IS_PUBLIC.getAttr()).equals(1);
        userTeamService.getUserIdMap(Collections.singletonList(paasFormDataEntityExt.getId()), corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), isPublic, mainUserMap, coUserMap);
        // 当前数据的创建人、负责人、协同人、当前操作人
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        BeanUtil.copyProperties(saasBaseDTO, handlerExplainDTO);
        handlerExplainDTO.setOwnerId(mainUserMap.getOrDefault(paasFormDataEntityExt.getId(), new ArrayList<>()));
        handlerExplainDTO.setCoUserId(coUserMap.getOrDefault(paasFormDataEntityExt.getId(), new ArrayList<>()));
        handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
        return ExplainUtil.isStageEdit(CustomerManagementEnum.CUSTOMER_STAGE.getAttr(), explainMap, handlerExplainDTO);
    }

    @Override
    public void afterJumpDeal(StageJumpDealDTO stageJumpDealDTO, PaasFormDataEntityExt paasFormDataEntityExt) throws XbbException {
        if (!Objects.equals(stageJumpDealDTO.getIsImport(), 1)) {
            Runnable stageRemindTask = () -> addStageTimeOutRemind(stageJumpDealDTO, paasFormDataEntityExt);
            threadPoolBeanConfig.stageRemindThreadPool().execute(stageRemindTask);
        }

        PaasStageEntity toStageEntity = stageJumpDealDTO.getToStageEntity();
        Boolean isNew = stageJumpDealDTO.getIsNew();
        if (Objects.nonNull(isNew) && isNew) {
            return;
        }
        if (Objects.isNull(toStageEntity)) {
            toStageEntity = new PaasStageEntity();
            toStageEntity.setName("开始阶段");
            toStageEntity.setType(StageTypeEnum.START_STAGE.getType());
            toStageEntity.setBusinessRelatedStatus(-1);
        }
        PaasStageEntity fromStageEntity = stageJumpDealDTO.getFromStageEntity();
        String nowStageName = fromStageEntity == null ? "开始阶段" : fromStageEntity.getName();
        Integer customerStatus = toStageEntity.getBusinessRelatedStatus();
        String customerName = paasFormDataEntityExt.getData().getString(CustomerManagementEnum.NAME.getAttr());
        String customerType = paasFormDataEntityExt.getData().getString(CustomerManagementEnum.TYPE.getAttr());
        String stageName = toStageEntity.getName();
        Integer stageType = toStageEntity.getType();
        String corpid = stageJumpDealDTO.getCorpid();
        Long customerId = paasFormDataEntityExt.getDataId();
        Long formId = stageJumpDealDTO.getFormId();
        String userId = stageJumpDealDTO.getUserId();
        String stageAttrName = stageJumpDealDTO.getStageAttrName();
        //客户阶段变更，触发评分
        scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT, corpid, customerId, null);
        String preStageMemo = StringUtil.isEmpty(nowStageName) ? "" : I18nMessageUtil.getMessage(CommonConstant.BY) + "“" + nowStageName + "”";
        Runnable runnable = () -> {
            try {
                // 生成项目日志
                List<DetailLogPojo> detailArr = new ArrayList();
                String oldTitle = nowStageName;
                String newTitle = stageName;
                String newMsg = String.format(SymbolConstant.BRACKETS_SQUARE_SOLID, newTitle);
                String oldMsg = String.format(SymbolConstant.BRACKETS_SQUARE_SOLID, oldTitle);
                detailArr.add(new DetailLogPojo(stageAttrName, stageAttrName, oldMsg, newMsg));
                PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(formId, corpid);
                String logName = FastJsonHelper.getStringOrDefaultFromFormData(paasFormDataEntityExt.getData(), CustomerManagementEnum.NAME.getAttr(), "");
                String memo = String.format(I18nMessageUtil.getMessage(I18nStringConstant.STAGE_OPERATION_LOG), stageJumpDealDTO.getLoginUserName(),
                        paasFormEntityExt.getName(), logName);
                String opObjectName = logName;
                mongoLogHelp.buildLog4DetailArr(detailArr, corpid, stageJumpDealDTO.getUserId(), stageJumpDealDTO.getLoginUserName(),
                        OperateModuleTypeEnum.CUSTOMER, OperateTypeEnum.EDIT, formId.toString(), opObjectName, memo, stageJumpDealDTO.getHttpHeader());
                String communicateMemo;
                if (Objects.equals(stageType, StageTypeEnum.FAIL_STAGE.getType())) {
                    //流失
                    Map<String, String> wastageReasonMap = dictionaryService.getDictionaryMap(DictionaryEnum.CUSTOMER_STAGE_WASTAGE, corpid, formId);
                    String wastageReason = wastageReasonMap.get(stageJumpDealDTO.getReasonId().toString());
                    communicateMemo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.DYNAMIC_USER_STAGE), stageJumpDealDTO.getLoginUserName(), paasFormEntityExt.getName(), nowStageName, stageName);
                    if (!StringUtil.isEmpty(wastageReason)) {
                        communicateMemo += "，" + CustomerManagementEnum.WASTAGE.getAttrName() + "：" + wastageReason;
                    }
                    communicateMemo += "；" + stageJumpDealDTO.getMemo();
                } else {
                    communicateMemo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.DYNAMIC_USER_STAGE), stageJumpDealDTO.getLoginUserName(), paasFormEntityExt.getName(), nowStageName, stageName);
                }

                // 动态
                if (Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(), stageJumpDealDTO.getDistributorMark())) {
                    CustomerDynamicAddDTO customerDynamicAddDTO =
                            CustomerDynamicAddDTO.initCustomerDynamicAddDTO(corpid, userId, null, communicateMemo, customerId, customerName, 0L, null, null, ProjectLogEnum.CUSTOMER_STAGE.getSubType());
                    customerDynamicAddDTO.setDistributorMark(stageJumpDealDTO.getDistributorMark());
                    customerCommunicateService.addCustomerDynamic(customerDynamicAddDTO);
                } else {
                    MainBusinessDynamicStrategy customerDynamicStrategy = dynamicStrategyFactory.getMainBusinessDynamicStrategyByBusinessType(stageJumpDealDTO.getBusinessType());
                    customerDynamicStrategy.stageJump(DynamicStageJumpDTO.initDynamicStageJumpDTO(stageJumpDealDTO, paasFormDataEntityExt, communicateMemo));
                }

                // 客户阶段变更消息推送
                List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.CUSTOMER_STAGE.getCode(),
                        PushTypeEnum.CUSTOMER_STAGE.getSubCode(), stageJumpDealDTO.getLoginUser(), paasFormDataEntityExt);
                PushRefTypePojo.Options options = null;
                MessageRabbitMqDTO messageRabbitMqDTO = null;
                if(CollectionsUtil.isNotEmpty(pushUserList)){
                     options = new PushRefTypePojo.Options(paasFormDataEntityExt.getAppId(), paasFormDataEntityExt.getMenuId(),
                            paasFormDataEntityExt.getFormId(), customerId, Collections.singletonList(customerId), SaasMarkEnum.SAAS.getCode(),
                            stageJumpDealDTO.getBusinessType(), stageJumpDealDTO.getBusinessType());
                     messageRabbitMqDTO = new MessageRabbitMqDTO(stageJumpDealDTO.getCorpid(), pushUserList, Collections.singletonList(customerId), 0,
                            null, I18nMessageUtil.getMessage(CustomerPushConstant.CUSTOMER_STAGE_CHANGE_TITLE),
                            String.format(I18nMessageUtil.getMessage(CustomerPushConstant.CUSTOMER_STAGE_CHANGE_CONTENT), stageJumpDealDTO.getLoginUserName(), customerName, stageName), null, options);
                    baseProducer.sendMessage(PushTypeEnum.CUSTOMER_STAGE, messageRabbitMqDTO);
                }
                // 未修改客户状态
                String type = dataDictionaryModel.getDictionaryValue(corpid, DictionaryEnum.CUSTOMER_STATUS, customerStatus);
                // 新老状态不一样才推送状态变更消息
                if (StringUtil.isNotEmpty(type) && !Objects.equals(customerType, type)) {
                    pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.CUSTOMER_CHANGE_PUSH.getCode(), PushTypeEnum.CUSTOMER_CHANGE_PUSH.getSubCode(), stageJumpDealDTO.getLoginUser(), paasFormDataEntityExt);
                    if(CollectionsUtil.isNotEmpty(pushUserList)){
                        options = new PushRefTypePojo.Options(paasFormDataEntityExt.getAppId(), paasFormDataEntityExt.getMenuId(), paasFormDataEntityExt.getFormId(), customerId, Collections.singletonList(customerId), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                        messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(customerId), 0, null, I18nMessageUtil.getMessage(CustomerPushConstant.CUSTOMER_STATUS_CHANGE_TITLE), String.format(I18nMessageUtil.getMessage(CustomerPushConstant.CUSTOMER_STATUS_CHANGE_CONTENT), stageJumpDealDTO.getLoginUserName(), customerName, type), null, options);
                        baseProducer.sendMessage(PushTypeEnum.CUSTOMER_CHANGE_PUSH, messageRabbitMqDTO);
                    }
                }
                scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT, corpid, customerId, null);
            } catch (Exception e) {
                log.error("客户阶段变更消息推送", e);
            }
        };
        threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
    }

    @Override
    public Integer approvalRequired(CommonJumpDTO commonJumpDTO, PaasFormDataEntityExt paasFormDataEntityExt, String stageAttr) throws XbbException {
        Integer noApprovalRequired = 1;
        Integer reasonId = commonJumpDTO.getReasonId();
        String memo = commonJumpDTO.getMemo();
        String corpid = commonJumpDTO.getCorpid();
        Long formId = commonJumpDTO.getFormId();
        Long customerId = paasFormDataEntityExt.getDataId();
        PaasStageEntity nextCustomerStageEntity = commonJumpDTO.getToStageEntity();
        String nextStageCode = "";
        Long nextStageId = 0L;
        Long nextStageProcessId = 0L;
        if (Objects.nonNull(nextCustomerStageEntity)) {
            nextStageCode = nextCustomerStageEntity.getCode();
            nextStageId = nextCustomerStageEntity.getId();
            nextStageProcessId = nextCustomerStageEntity.getStageProcessId();
        }
        if (commonHelp.isOpenWorkFlow(corpid)) {
            // 新工作流
            List<WorkflowEntity> workflowEntities = workflowFormDataOperationService.getSatisfyTriggerEntitys(corpid, formId, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), Arrays.asList(TriggerEventTypeEnum.ONLY_UPDATE.getType(), TriggerEventTypeEnum.ADD_OR_UPDATE.getType()));
            for (WorkflowEntity workflowEntity : workflowEntities) {
                WorkflowNodeEntity startNode = workflowNodeModel.getByUId(workflowEntity.getId(), corpid, "startNode");
                FormTriggerNode formTriggerNode = JSON.parseObject(startNode.getConfigData(), FormTriggerNode.class);
                if (CollectionsUtil.isEmpty(formTriggerNode.getNeedApproveFields()) || formTriggerNode.getNeedApproveFields().contains(CustomerManagementEnum.CUSTOMER_STAGE.getAttr())) {
                    //是否启用新工作流
                    PaasFormExplainEntity explain = paasFormExplainModel.getByFormId(formId, corpid);
                    Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explain.getExplains(), null);
                    BusinessRuleInfoPojo businessRuleInfoPojo = new BusinessRuleInfoPojo(startNode.getCorpid(), startNode.getFormId(), startNode.getBusinessType(), startNode.getSaasMark(),explainMap);
                    PaasFormDataEntityExt paasFormDataEntityExtClone = (PaasFormDataEntityExt) CloneUtil.deepClone(paasFormDataEntityExt);
                    if (Objects.nonNull(nextCustomerStageEntity)) {
                        // 详情页阶段跳转，用跳转之后的阶段去匹配触发条件-----59089 【KA大客户】【B级】阶段审批异常
                        paasFormDataEntityExtClone.getData().put(stageAttr, nextCustomerStageEntity.getCode());
                    }
                    boolean flag = workflowFormDataOperationService.validatePreCondition(formTriggerNode.getTriggerConditions(), paasFormDataEntityExtClone, businessRuleInfoPojo);
                    if(!flag){
                        break;
                    }
                    workflowRequired(paasFormDataEntityExt, startNode, commonJumpDTO,  WorkflowExecutionTypeEnum.FORM, stageAttr, null);

                    if (Objects.equals(1, workflowEntity.getIsApprove())) {
                        noApprovalRequired = 3;
                    } else {
                        // 无审批节点
                        noApprovalRequired = 4;
                    }
                    break;
                }
            }
        } else {
            // 老审批
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", 0);
            params.put("corpid", corpid);
            params.put("formId", formId);
            params.put("businessType", XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            params.put("enable", 1);
            List<PaasProcessTemplateEntityExt> paasProcessTemplateEntityExtList = paasProcessTemplateModel.list(params);
            if (paasProcessTemplateEntityExtList.size() > 0 && paasProcessTemplateEntityExtList.get(0).getNeedApproveFieldList().contains(CustomerManagementEnum.CUSTOMER_STAGE.getAttr())) {
                JSONObject newData = (JSONObject) CloneUtil.deepClone(paasFormDataEntityExt.getData());
                newData.put(CustomerManagementEnum.CUSTOMER_STAGE.getAttr(), nextStageCode);
                newData.put(PaasStageEnum.STAGE_PROCESS_ID.getAttr(), nextStageProcessId);
                newData.put(PaasStageEnum.STAGE_ID.getAttr(), nextStageId);

                // 计算阶段比例
                StageJumpHandle stageJumpHandle = stageJumpMap.get(nextCustomerStageEntity.getType());
                Integer proportion = stageJumpHandle.getJumpIntoProportion(paasFormDataEntityExt.getId(), corpid, formId, nextCustomerStageEntity.getId(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), nextCustomerStageEntity.getOutProportion());

                newData.put(PaasStageEnum.STAGE_RATIO.getAttr(), proportion);
                Map<Integer, List<UserTeamEntity>> userMap = userTeamService.getUserTeam(paasFormDataEntityExt.getId(), corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                // 负责人
                if (userMap.containsKey(1)) {
                    List<UserTeamEntity> mainUserList = userMap.get(1);
                    List<String> mainIdList = new ArrayList<>();
                    for (UserTeamEntity userTeamEntity : mainUserList) {
                        mainIdList.add(userTeamEntity.getUserId());
                    }
                    newData.put(CustomerManagementEnum.OWNER_ID.getAttr(), mainIdList);
                }
                if (userMap.containsKey(0)) {
                    List<UserTeamEntity> coUserList = userMap.get(0);
                    List<String> coIdList = new ArrayList<>();
                    for (UserTeamEntity userTeamEntity : coUserList) {
                        coIdList.add(userTeamEntity.getUserId());
                    }
                    newData.put(CustomerManagementEnum.COUSERID.getAttr(), coIdList);
                }
                Integer customerStatus = nextCustomerStageEntity.getBusinessRelatedStatus();
                boolean isChangeCustomerType = customerStatus != null && customerStatus != 0 && Objects.equals(nextCustomerStageEntity.getOpenStatus(), 1);
                if (isChangeCustomerType) {
                    //更改客户状态
                    newData.put(CustomerManagementEnum.TYPE.getAttr(), customerStatus.toString());
                }
                if (Objects.equals(nextCustomerStageEntity.getType(), StageTypeEnum.FAIL_STAGE.getType())) {
                    if (Objects.nonNull(commonJumpDTO.getReasonId())) {
                        newData.put(CustomerManagementEnum.WASTAGE.getAttr(), commonJumpDTO.getReasonId().toString());
                    }
                    newData.put(CustomerManagementEnum.WASTAGE_MEMO.getAttr(), commonJumpDTO.getMemo());
                }
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termQuery(ContactEnum.getEsAttr4Keyword(ContactEnum.CUSTOMER_NAME), customerId));
                List<PaasFormDataEntityExt> paasFormDataEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTACT, boolQueryBuilder, PaasFormDataEntityExt.class, null);
                if (CollectionsUtil.isNotEmpty(paasFormDataEntityList)) {
                    LinkFormItemDTO linkFormItemDTO = new LinkFormItemDTO();
                    BeanUtil.copyProperties(commonJumpDTO, linkFormItemDTO);
                    paasFormExplainService.checkDataHavaEditAndDelPermission(paasFormDataEntityList, XbbRefTypeEnum.CONTACT.getCode(), linkFormItemDTO, true);
                    newData.put(CustomerManagementEnum.ADD_CONTACT.getAttr(), paasFormDataEntityList);

                }
                StartProcessDTO startProcessDTO = new StartProcessDTO();
                BeanUtil.copyProperties(commonJumpDTO, startProcessDTO);
                BeanUtil.copyProperties(paasFormDataEntityExt, startProcessDTO);
                startProcessDTO.setData(newData);
                startProcessDTO.setFormDataId(paasFormDataEntityExt.getId());
                startProcessDTO.setCreatorId(commonJumpDTO.getUserId());
                startProcessDTO.setSaasMark(1);
                startProcessDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                StartProcessVO startProcessVO = processStartHelp.startProcess(startProcessDTO, paasFormDataEntityExt);
                noApprovalRequired = startProcessVO.getNoApprovalRequired();
            }
        }
        return noApprovalRequired;
    }

    @Override
    public void workflowRequired(PaasFormDataEntityExt paasFormDataEntityExt, WorkflowNodeEntity startNode, CommonJumpDTO commonJumpDTO, WorkflowExecutionTypeEnum workflowExecutionTypeEnum, String stageAttr, WorkflowExecutionEntity workflowExecutionEntity) throws XbbException {
        String corpid = commonJumpDTO.getCorpid();
        Long formId = commonJumpDTO.getFormId();
        Long customerId = paasFormDataEntityExt.getDataId();
        PaasStageEntity nextCustomerStageEntity = commonJumpDTO.getToStageEntity();
        String nextStageCode = "";
        Long nextStageId = 0L;
        Long nextStageProcessId = 0L;
        Integer proportion = 0;
        if (Objects.nonNull(nextCustomerStageEntity)) {
            nextStageCode = nextCustomerStageEntity.getCode();
            nextStageId = nextCustomerStageEntity.getId();
            nextStageProcessId = nextCustomerStageEntity.getStageProcessId();
            // 计算阶段比例
            StageJumpHandle stageJumpHandle = stageJumpMap.get(nextCustomerStageEntity.getType());
            proportion = stageJumpHandle.getJumpIntoProportion(paasFormDataEntityExt.getId(), corpid, formId, nextCustomerStageEntity.getId(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), nextCustomerStageEntity.getOutProportion());
        }

        // backup
        JSONObject oldDataObj = (JSONObject) CloneUtil.deepClone(paasFormDataEntityExt.getData());
        FormDataUtil.setSystemData(oldDataObj, paasFormDataEntityExt);
        long now = DateTimeUtil.getInt();
        List<CustomerUserEntity> contactList = customerUserModel.getByCustomerId(corpid, paasFormDataEntityExt.getId());
        oldDataObj.put(StringConstant.USER_TEAM, contactList);
        WorkflowBackupDataEntity workflowBackupDataEntity = new WorkflowBackupDataEntity(corpid, paasFormDataEntityExt.getAppId(), paasFormDataEntityExt.getFormId(), paasFormDataEntityExt.getMenuId(), 0L, 0L, paasFormDataEntityExt.getId(), oldDataObj, now, now, DelEnum.NORMAL.getDel());
        workflowBackupDataModel.insert(workflowBackupDataEntity);
        //构建mq消息
        FormDataUtil.setSystemData(paasFormDataEntityExt.getData(), paasFormDataEntityExt);
        Data oldData = new Data(startNode.getAppId(), startNode.getMenuId(), startNode.getFormId(), paasFormDataEntityExt.getId(),
                oldDataObj, startNode.getBusinessType(), startNode.getSaasMark(), startNode.getId(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());

        // 将需要更新的字段，更新到主数据
        JSONObject updateDataJson = new JSONObject();
        updateDataJson.put(CustomerManagementEnum.CUSTOMER_STAGE.getAttr(), nextStageCode);
        Integer customerStatus = nextCustomerStageEntity.getBusinessRelatedStatus();
        boolean isChangeCustomerType = customerStatus != null && customerStatus != 0 && Objects.equals(nextCustomerStageEntity.getOpenStatus(), 1);
        if (isChangeCustomerType) {
            //更改客户状态
            updateDataJson.put(CustomerManagementEnum.TYPE.getAttr(), customerStatus.toString());
        }
        if (Objects.equals(nextCustomerStageEntity.getType(), StageTypeEnum.FAIL_STAGE.getType())) {
            if (Objects.nonNull(commonJumpDTO.getReasonId())) {
                updateDataJson.put(CustomerManagementEnum.WASTAGE.getAttr(), commonJumpDTO.getReasonId().toString());
            }
            updateDataJson.put(CustomerManagementEnum.WASTAGE_MEMO.getAttr(), commonJumpDTO.getMemo());
        }
        // 存放阶段流程id
        updateDataJson.put(PaasStageEnum.STAGE_PROCESS_ID.getAttr(), nextStageProcessId);
        // 存放阶段id
        updateDataJson.put(PaasStageEnum.STAGE_ID.getAttr(), nextStageId);

        updateDataJson.put(PaasStageEnum.STAGE_RATIO.getAttr(), proportion);
        UpdateDataEntity updateData = ExplainUtil.getUpdateData(customerId, updateDataJson, corpid);
        customerModel.updateBatch(Collections.singletonList(updateData), corpid, WriteRequest.RefreshPolicy.NONE);
        // 将需要更新的字段存入上下文中
        paasFormDataEntityExt.getData().putAll(updateDataJson);
        WorkflowTransferPOJO workflowTransferPOJO = WorkflowTransferHelp.createTransferData(paasFormDataEntityExt, null, null, null, corpid,
                commonJumpDTO.getLoginUser(), startNode, WorkflowOperateEnum.UPDATE.getType(), 0, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        workflowTransferPOJO.setBackupDataId(workflowBackupDataEntity.getId());
        workflowTransferPOJO.setOldData(oldData);

        workflowTransferPOJO.setExecutionType(workflowExecutionTypeEnum.getCode());
        workflowTransferPOJO.setIsFromStage(true);
        workflowTransferPOJO.setToStageId(nextStageId);
        if (Objects.isNull(commonJumpDTO.getFromStageEntity())) {
            workflowTransferPOJO.setFromStageId(null);
        } else {
            workflowTransferPOJO.setFromStageId(commonJumpDTO.getFromStageEntity().getId());
        }
        if (!Objects.isNull(workflowExecutionEntity)) {
            workflowTransferPOJO.setParentExecutionId(workflowExecutionEntity.getId());
            workflowTransferPOJO.setLinkKey(workflowExecutionEntity.getLinkKey());
        }
        workflowTransferPOJO.setStageProcessId(commonJumpDTO.getStageProcessEntity().getId());

        JSONObject newDataObj = new JSONObject();
        newDataObj.putAll(oldDataObj);
        newDataObj.putAll(updateDataJson);
        Data newData = new Data(startNode.getAppId(), startNode.getMenuId(), startNode.getFormId(), paasFormDataEntityExt.getId(),
                newDataObj, startNode.getBusinessType(), startNode.getSaasMark(), startNode.getId(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        workflowTransferPOJO.setData(newData);

        // 发送到消费者
        WorkflowRabbitmqDTO workflowRabbitmqDTO = new WorkflowRabbitmqDTO(workflowTransferPOJO, startNode, new SaasNeedRedundantAttrPojo());
        workflowProducer.startWorkflow(workflowRabbitmqDTO);
    }

    @Override
    public void jumpSpecialDeal(StageJumpSpecialDealDTO stageJumpSpecialDealDTO) throws XbbException {
        //客户转跳到输单，输单原因，备注更新
        String corpid = stageJumpSpecialDealDTO.getCorpid();
        Long dataId = stageJumpSpecialDealDTO.getDataId();
        String memo = stageJumpSpecialDealDTO.getMemo();
        PaasStageEntity toStageEntity = stageJumpSpecialDealDTO.getToStageEntity();
        Integer type = toStageEntity.getType();
        Integer openStatus = toStageEntity.getOpenStatus();
        Integer businessRelatedStatus = toStageEntity.getBusinessRelatedStatus();
        Integer reasonId = stageJumpSpecialDealDTO.getReasonId();
        Integer customerType = DictionaryEnum.CUSTOMER_STATUS.getType();
        Integer fromApproval = stageJumpSpecialDealDTO.getFromApproval();
        Long formId = stageJumpSpecialDealDTO.getFormId();
        try {
            //每完成一项阶段工作时的完成时间影响客户的最后跟进时间
            Boolean flag = paasFormService.getSingleRuleList(corpid, RuleSettingEnum.STAGE_JUMP_GO_TO_TIME.getConfig(), formId);
            if (flag) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put(CustomerManagementEnum.LAST_CONNECT_TIME.getAttr(), DateTimeUtil.getInt());
                UpdateDataEntity updateData = ExplainUtil.getUpdateData(dataId, jsonObject, corpid);
                customerModel.updateBatch(Collections.singletonList(updateData), corpid, WriteRequest.RefreshPolicy.NONE);
            }

            Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 客户转跳特殊逻辑：判断转跳的阶段是否关联客户状态
            // 更新客户状态前还需要判断客户该客户状态是否删除或未启用
            boolean dataDicBool = false;
            DataDictionaryEntity dataDictionaryEntity = dataDictionaryModel.getByType(customerType, corpid);
            if (Objects.nonNull(dataDictionaryEntity)) {
                List<DictionaryPojo> dictionaryPojoList = JSONArray.parseArray(dataDictionaryEntity.getData(), DictionaryPojo.class);
                if (CollectionsUtil.isNotEmpty(dictionaryPojoList)) {
                    for (DictionaryPojo e : dictionaryPojoList) {
                        if (Objects.equals(e.getValue(), String.valueOf(businessRelatedStatus)) && Objects.equals(e.getEnable(), 1)) {
                            dataDicBool = true;
                        }
                    }
                }
            }
            if (Objects.equals(openStatus, 1) && dataDicBool) {
                map.put(CustomerManagementEnum.TYPE.getAttr(), String.valueOf(businessRelatedStatus));
            }
            // 转跳到失败阶段，客户的跳转特殊逻辑：更新主数据，输单原因与备注
            if (Objects.nonNull(type) && Objects.equals(type, StageTypeEnum.FAIL_STAGE.getType())&& !Objects.equals(1, fromApproval)) {
                map.put(CustomerManagementEnum.WASTAGE_MEMO.getAttr(), memo);
                map.put(CustomerManagementEnum.WASTAGE.getAttr(), reasonId);
            }
            if (!map.isEmpty()) {
                customerModel.jsonsetNoSubById(corpid, dataId, map);
            }
            //客户评分重新修改一下
            scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT, corpid, dataId, null);
        } catch (Exception e) {
            log.error("转跳到失败阶段，客户更新备注与评分出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }
}
